import asyncio


class Hige:
  def __init__(self, logger, pair, lot, delta):
    self._logger = logger
    self._pair   = pair
    self._lot    = lot
    self._delta  = delta

    self._remain = 0

    self._sell_price = 0
    self._buy_price  = 0
    self._sell       = None
    self._buy        = None

    self._total = 0

    asyncio.create_task(self._main())

  async def _main(self):
    self._logger.info("started")
    while True:
      pair  = self._pair
      depth = pair.depth

      if len(depth.bids) == 0 or len(depth.asks) == 0:
        await depth.wait()
        continue

      expected_sell_price = depth.asks[0][0] + self._delta
      expected_buy_price  = depth.bids[0][0] - self._delta

      if self._sell is not None:
        await self._sell.update()
        if self._sell.done:
          amount = self._sell.amount - self._sell.remain
          income = amount * self._sell.price
          self._remain -= amount
          self._total  += income
          self._sell    = None
          if amount > 0:
            self._logger.info(f"<SELL> {amount} / {income} ({self._remain} / {self._total})")
          continue
        elif self._sell_price != expected_sell_price:
          await self._sell.cancel()
          continue
      elif self._remain > pair.order_unit:
        amount           = min(self._lot, self._remain)
        self._sell_price = expected_sell_price
        self._sell       = await pair.sell_limit(amount, self._sell_price)

      if self._buy is not None:
        await self._buy.update()
        if self._buy.done:
          amount = self._buy.amount - self._buy.remain
          outgo  = amount * self._buy.price
          self._total  -= outgo
          self._remain += amount
          self._buy     = None
          if amount > 0:
            self._logger.info(f"<BUY> {amount} / {outgo} ({self._remain} / {self._total})")
          continue
        elif self._buy_price != expected_buy_price:
          await self._buy.cancel()
          continue
      elif self._remain < self._lot*3:
        self._buy_price = expected_buy_price
        self._buy       = await pair.buy_limit(self._lot, self._buy_price)

      await asyncio.sleep(5)

  async def _reset_order(order, price):
    if not order.done and order.price != price:
      await order.cancel()
